package cn.hamster3.mc.plugin.core.common.util;

import cn.hamster3.mc.plugin.core.common.config.ConfigSection;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;

public final class UpdateCheckUtils {
    private static final JsonParser JSON_PARSER = new JsonParser();

    private UpdateCheckUtils() {
    }

    public static void showUpdate(@NotNull String pluginName, @NotNull ConfigSection config, @NotNull UpdateReceiver sender) {
        String version = config.getString("version");
        if (version == null) {
            return;
        }
        String checkType = config.getString("CHECK_TYPE", "");
        try {
            switch (checkType) {
                case "GITEA_RELEASES": {
                    String baseUrl = config.getString("GIT_BASE_URL");
                    String gitRepo = config.getString("GIT_REPO");
                    String downloadUrl = config.getString("DOWNLOAD_URL");
                    if (baseUrl == null || gitRepo == null || downloadUrl == null) {
                        return;
                    }
                    String gitToken = config.getString("GIT_TOKEN");
                    String lastRelease = getGiteaLastRelease(baseUrl, gitRepo, gitToken);
                    if (lastRelease == null) {
                        break;
                    }
                    if (lastRelease.compareToIgnoreCase(version) <= 0) {
                        break;
                    }
                    sender.sendMessage(String.format("§a插件 §l%s§a 发布了新版本 %s", pluginName, lastRelease));
                    sender.sendMessage(String.format("§b下载链接: §n%s", downloadUrl));
                    break;
                }
                case "GITLAB_RELEASES": {
                    String baseUrl = config.getString("GIT_BASE_URL");
                    String gitRepo = config.getString("GIT_REPO");
                    String downloadUrl = config.getString("DOWNLOAD_URL");
                    if (baseUrl == null || gitRepo == null || downloadUrl == null) {
                        return;
                    }
                    String gitToken = config.getString("GIT_TOKEN");
                    int projectID = getGitlabProjectID(baseUrl, gitRepo, gitToken);
                    if (projectID < 0) {
                        break;
                    }
                    String lastRelease = getGitlabLastRelease(baseUrl, projectID, gitToken);
                    if (lastRelease == null) {
                        break;
                    }
                    if (lastRelease.compareToIgnoreCase(version) <= 0) {
                        break;
                    }
                    sender.sendMessage(String.format("§a插件 §l%s§a 发布了新版本 %s", pluginName, lastRelease));
                    sender.sendMessage(String.format("§b下载链接: §n%s", downloadUrl));
                    break;
                }
            }
        } catch (Exception ignored) {
        }
    }

    @Nullable
    public static String getGiteaLastRelease(@NotNull String baseUrl, @NotNull String repo, @Nullable String token) throws IOException {
        URL url = new URL(baseUrl + "/api/v1/repos/" + repo + "/releases?limit=10");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoInput(true);
        connection.setRequestMethod("GET");
        if (token != null) {
            connection.setRequestProperty("Authorization", "token " + token);
        }
        connection.connect();
        try (InputStream stream = connection.getInputStream()) {
            try (InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) {
                JsonArray array = JSON_PARSER.parse(reader).getAsJsonArray();
                for (JsonElement element : array) {
                    JsonObject object = element.getAsJsonObject();
                    //noinspection SpellCheckingInspection
                    if (object.get("prerelease").getAsBoolean()) {
                        continue;
                    }
                    return object.get("name").getAsString();
                }
            }
        }
        return null;
    }

    public static int getGitlabProjectID(@NotNull String baseUrl, @NotNull String repo, @Nullable String token) throws IOException {
        URL url = new URL("https://" + baseUrl + "/api/v4/projects?search=" + repo);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoInput(true);
        connection.setRequestMethod("GET");
        if (token != null) {
            connection.setRequestProperty("PRIVATE-TOKEN", "token " + token);
        }
        connection.connect();
        try (InputStream stream = connection.getInputStream()) {
            try (InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) {
                JsonArray array = JSON_PARSER.parse(reader).getAsJsonArray();
                for (JsonElement element : array) {
                    JsonObject object = element.getAsJsonObject();
                    return object.get("id").getAsInt();
                }
            }
        }
        return -1;
    }

    @Nullable
    public static String getGitlabLastRelease(@NotNull String baseUrl, int repo, @Nullable String token) throws IOException {
        URL url = new URL(baseUrl + "/api/v4/projects/" + repo + "/releases/permalink/latest");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoInput(true);
        connection.setRequestMethod("GET");
        if (token != null) {
            connection.setRequestProperty("Authorization", "token " + token);
        }
        connection.connect();
        try (InputStream stream = connection.getInputStream()) {
            try (InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) {
                JsonObject object = JSON_PARSER.parse(reader).getAsJsonObject();
                return object.get("name").getAsString();
            }
        }
    }

    public interface UpdateReceiver {
        void sendMessage(@NotNull String message);
    }
}
